#include "Logging.h"
#include "Console.h"
#include "string.h"

namespace CEngine
{

Logging::Logging(const U8 v, const bool tc, const bool tf, const U8 cpl)
    :   toConsole(tc),
        toFile(tf),
        verbosity(v),
        charactersPerLine(cpl),
        totalLinesPrinted(0)
{}

void
Logging::log(const System system, const U8 v, const char* input, ...) {
    if(v > verbosity)
        return;

    CHAR buffer[charactersPerLine + 2];
    U8 bufferPosition = 0;
    U8 lastSpace = 0;

    va_list args;
    va_start(args, input);
    U32 totalStringLength = 0;

    CHAR formattedInput[1024];
    U16 charactersFormatted = 0;
    charactersFormatted = Console::vsPrint(formattedInput, 1024, input, args);

    Console::TextColour foreground, background = Console::BLACK;

    switch(system) {
        case MEMORY:    foreground = Console::GREEN;
            break;
        case SETTINGS:  foreground = Console::LAQUA;
            break;
        case CONTAINERS:foreground = Console::LGREEN;
            break;
        case FILESYSTEM:foreground = Console::BLUE;
            background = Console::GRAY;
            break;
        case STRINGS:   foreground = Console::LYELLOW;
            break;
        default:        foreground = Console::LWHITE;
    }

    switch(v) {
        case LOG_ERROR:     background = Console::LRED;
                            break;
        case LOG_WARNING:   background = Console::LYELLOW;
                            break;
    }

    Console::setTextColour(foreground, background);

    for (U8 i = 0; formattedInput[i] != '\0' ; ++i) {
        if(bufferPosition <= charactersPerLine && buffer[bufferPosition - 1] == ' ') {
            lastSpace = bufferPosition - 1;
        }
        if(buffer[bufferPosition - 1] == '\n' && bufferPosition <= charactersPerLine - 1) {
            buffer[bufferPosition] = '\0';

            if(toConsole)
                    Console::vPrint(buffer, args);

                bufferPosition = 0;
                lastSpace = 0;
                totalStringLength = 0;
                ++totalLinesPrinted;
                --i;
        }
        else if(bufferPosition + totalStringLength >= charactersPerLine) {
            if(lastSpace <= bufferPosition - 20) {
                buffer[bufferPosition - 2] = '\n';
                buffer[bufferPosition - 1] = '\0';

                if(toConsole)
                    Console::vPrint(buffer, args);

                bufferPosition = 0;
                lastSpace = 0;
                totalStringLength = 0;
                -- --i;
                ++totalLinesPrinted;
            }
            else {
                buffer[lastSpace] = '\n';
                buffer[lastSpace + 1] = '\0';

                if(toConsole)
                    Console::vPrint(buffer, args);

                i -= bufferPosition - lastSpace;
                bufferPosition = 0;
                lastSpace = 0;
                totalStringLength = 0;
                ++totalLinesPrinted;
            }
        }
        else {
            buffer[bufferPosition] = formattedInput[i];
            ++bufferPosition;
        }
    }

    if(buffer[bufferPosition - 1] != '\n' && bufferPosition > 0) {
        buffer[bufferPosition] = '\n';
        buffer[bufferPosition + 1] = '\0';
    }
    else {
        buffer[bufferPosition] = '\0';
    }
    Console::vPrint(buffer, args);
    ++totalLinesPrinted;

    va_end(args);

    Console::setTextColour(Console::RESET, Console::RESET);

    if(charactersFormatted >= 1024) {
        Console::setTextColour(Console::RED, Console::BLACK);
        Console::print("Log input was greater than 1023 characters.\n");
        Console::setTextColour(Console::RESET, Console::RESET);
    }
}

}
